#include <fstream>
#include <vector>
#include <algorithm>
#include <numeric>

#include "geometry.h"
#include "node.h"

template <class It>
void sortByRotation( It first, It last, Vertex::Rotation r ) {
    // если фигурка выпуклая, то просто берем первую вершину
    auto center = std::accumulate( first, last, Point( 0, 0 ) );
    center.x /= std::distance( first, last );
    center.y /= std::distance( first, last );
    std::sort( first, last, [&center, &r]( const Point & a, const Point & b ) {
        switch ( r )
        {
            case Vertex::Rotation::CLOCKWISE:
                return Edge::polarAngle( Edge( center, a ) ) >= Edge::polarAngle( Edge( center, b ) );
            case Vertex::Rotation::COUNTERCLOCKWISE:
                return Edge::polarAngle( Edge( center, a ) ) < Edge::polarAngle( Edge( center, b ) );
        }
    } );
}

enum Result
{
    BOTH_IN = 0,
    BOTH_OUT_SLICE = 1,
    PARTIAL_IN = 2,
    BOTH_OUT = 3,
};

Result crossing( const Edge & e, const Figure & f ) {
    bool fstIn = f.isPointIn( e.from );
    bool sndIn = f.isPointIn( e.to );
    if ( fstIn && sndIn )
    {
        return BOTH_IN;
    } else if ( fstIn || sndIn )
    {
        return PARTIAL_IN;
    } else if ( f.isCrossing( e ) )
    {
        return BOTH_OUT_SLICE;
    } else
        return BOTH_OUT;
}

const std::string figureFileName = "polys.txt";
const std::string linesFileName = "lines.txt";
const std::string resultFileName = "result.txt";

auto readPoints( std::ifstream & f ) {
    std::vector<Point> pv;
    std::vector<std::string> ps;
    std::string s;
    while ( f >> s )
    { ps.push_back( std::move( s ) ); }
    std::transform( ps.begin(), ps.end(), std::back_inserter( pv ),
                    []( const std::string & str ) { return Point( std::stoi( str ), std::stoi( str.substr( str.find( ',' ) + 1 ) ) ); } );
    return pv;
}

auto makeFigure( const std::vector<Point> & points ) {
    auto v = std::make_unique<Vertex>( points[0] );
    for ( size_t i = 1; i < points.size(); ++i )
    { v->insert( new Vertex( points[i] ) ); }
    return std::make_unique<Figure>( std::move( v ) );
}

int main( int argc, char ** argv ) {
    std::ifstream figureFile( figureFileName );
    std::ifstream linesFile( linesFileName );
    std::ofstream resultFile( resultFileName, std::ios_base::trunc );

    if ( figureFile.good() && linesFile.good() && resultFile.good() )
    {
        auto figurePoints = readPoints( figureFile );
        //sortByRotation(figurePoints.begin(), figurePoints.end(), Vertex::Rotation::CLOCKWISE);
        auto linePoints = readPoints( linesFile );
        auto f = makeFigure( figurePoints );
        for ( size_t i = 0; i < linePoints.size(); i += 2 )
        { resultFile << crossing( Edge( linePoints.at( i ), linePoints.at( i + 1 ) ), *f ) << "\n"; }
        return 0;
    } else
        return 1;
}
